﻿//#define DECODE_RGB
#define ANALYZE

using System;
using System.Drawing;
using System.Windows.Forms;
using HCVideo;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;
using VisionLibaray;

namespace HCNetSDKTest
{
    public partial class Form1 : Form
    {
        #region Member Variable

        //登录标识
        private int lUserID = -1;
        //预览标识
        private int lRealHandle = -1;

        private HCNetSDK.RealDataCallBack_V30 RealDataCallBack;
        private HCNetSDK.DecCBFun DecCBCallbackHandle;
        #endregion

        Size sizeImage, sizeVision, sizeBlock, sizeMove;
        Point pCenter;
        Rectangle rectCenter;
        Random R = new Random();

        Bitmap bmpDecode = null;
        Bitmap bmpVision = null;
        Bitmap bmpBoundary = null;
        Bitmap bmpGreyEnhance = null;
        Bitmap bmpAbstract = null;
        Bitmap bmpStable = null;
        Bitmap bmpSubtract = null;
        Bitmap bmpShake = null;

        public Form1()
        {
            this.SetStyle(
                ControlStyles.AllPaintingInWmPaint
                | ControlStyles.OptimizedDoubleBuffer
                | ControlStyles.UserPaint
                , true);
            InitializeComponent();

            RealDataCallBack = new HCNetSDK.RealDataCallBack_V30(RealData);

            sizeVision = new Size(352, 288);

            sizeImage = new Size(704, 576);

            bmpDecode = new Bitmap(sizeImage.Width, sizeImage.Height);

            bmpStable = new Bitmap(sizeVision.Width, sizeVision.Height);

            bmpSubtract = new Bitmap(sizeVision.Width, sizeVision.Height);

            bmpShake = new Bitmap(sizeVision.Width, sizeVision.Height);

            bmpVision = new Bitmap(sizeVision.Width, sizeVision.Height);

            bmpBoundary = new Bitmap(sizeVision.Width, sizeVision.Height);

            bmpGreyEnhance = new Bitmap(sizeVision.Width, sizeVision.Height);



            sizeBlock = new Size(4, 4);
            sizeMove = new Size(16, 12);

            bmpAbstract = new Bitmap(
                sizeVision.Width / sizeMove.Width,
                sizeVision.Height / sizeMove.Height);

            pCenter = new Point(sizeImage.Width / 2, sizeImage.Height / 2);

            rectCenter = new Rectangle(
                    (pDecode.Bounds.X + pCenter.X / 2 - sizeVision.Width / 4),
                    (pDecode.Bounds.Y + pCenter.Y / 2 - sizeVision.Height / 4),
                    sizeVision.Width / 2,
                    sizeVision.Height / 2);
        }

        int m_iPort = -1;
        bool bInit = false;
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            this.tBDeviceIP.Text = Properties.Settings.Default.DeviceIP;
        }

        private void btnLogin_Click(object sender, EventArgs e)
        {
            bInit = HCNetSDK.NET_DVR_Init();
            HCNetSDK.NET_DVR_SetConnectTime(5000, 1);

            if (!bInit)
            {
                MessageBox.Show("初始化失败");

                return;
            }

            NET_DVR_DEVICEINFO dev = new NET_DVR_DEVICEINFO();
            lUserID = HCNetSDK.NET_DVR_Login(
                tBDeviceIP.Text, 8000, "admin", "12345", out dev);

            if (lUserID >= 0)
            {
                btnOpen.Enabled = true;
                btnData.Enabled = true;
                btnLogin.Enabled = false;

                Properties.Settings.Default.DeviceIP = this.tBDeviceIP.Text;
                Properties.Settings.Default.Save();
            }


        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            if (lUserID == -1) return;

            #region New V30
            NET_DVR_CLIENTINFO clientinfo = new NET_DVR_CLIENTINFO();
            clientinfo.hPlayWnd = this.pStream.Handle;//视频窗口
            clientinfo.lChannel = 1; // 通道号
            clientinfo.lLinkMode = 0;
            clientinfo.sMultiCastIP = "";

            lRealHandle = HCNetSDK.NET_DVR_RealPlay(lUserID, ref clientinfo);

            if (lRealHandle == -1) return;

            btnOpen.Enabled = false;
            btnData.Enabled = false;

            #endregion
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            if (lRealHandle >= 0) HCNetSDK.NET_DVR_StopRealPlay(lRealHandle);
            if (lUserID >= 0) HCNetSDK.NET_DVR_Logout(lUserID);
            if (bInit) HCNetSDK.NET_DVR_Cleanup();

            this.Close();
        }

        private void btnData_Click(object sender, EventArgs e)
        {
            if (lUserID == -1) return;

            NET_DVR_CLIENTINFO clientinfo = new NET_DVR_CLIENTINFO();
            //clientinfo.hPlayWnd = IntPtr.Zero;//视频窗口
            clientinfo.hPlayWnd = this.pStream.Handle;//视频窗口
            clientinfo.lChannel = 1; // 通道号
            clientinfo.lLinkMode = 0;
            clientinfo.sMultiCastIP = "";

            lRealHandle = HCNetSDK.NET_DVR_RealPlay_V30(lUserID, ref clientinfo, RealDataCallBack, 0, true);

            if (lRealHandle == -1) return;

            btnOpen.Enabled = false;
            btnData.Enabled = false;
        }

        //IntPtr转换成byte[]
        public byte[] ConvertToBytes(IntPtr dataBuf, int length)
        {
            byte[] byteBuf = new byte[length];
            Marshal.Copy(dataBuf, byteBuf, 0, length);
            return byteBuf;
        }

        private InitDecoderCallback InitDecoderHandle;
        private InputDecoderCallback InputDecoderHandle;
        void RealData(int lRealHandle, uint dwDataType, IntPtr pBuffer, uint dwBufSize, IntPtr pUser)
        {
            if (dwDataType == HCNetSDK.NET_DVR_SYSHEAD && m_iPort < 0)
            {
                do
                {
                    if (!HCNetSDK.PlayM4_GetPort(ref m_iPort)) break;

                    if (!HCNetSDK.PlayM4_SetStreamOpenMode(m_iPort, HCNetSDK.STREAME_REALTIME)) break;

                    if (!HCNetSDK.PlayM4_OpenStream(m_iPort, pBuffer, dwBufSize, 1024 * 1024)) break;

                    if (!HCNetSDK.PlayM4_GetPictureSize(m_iPort, out pWidth, out pHeight)) break;

                    if (!HCNetSDK.PlayM4_SetDecCBStream(m_iPort, 1)) break;

                    DecCBCallbackHandle = new HCNetSDK.DecCBFun(DecCallBack);
                    if (!HCNetSDK.PlayM4_SetDecCallBack(m_iPort, DecCBCallbackHandle)) break;

                    if (!HCNetSDK.PlayM4_Play(m_iPort, IntPtr.Zero)) break;
                } while (false);
            }
            else if (dwDataType == HCNetSDK.NET_DVR_STREAMDATA)
            {
                HCNetSDK.PlayM4_InputData(m_iPort, pBuffer, dwBufSize);
            }


            //IntPtr DecContain = Marshal.AllocCoTaskMem((int)dwBufSize);
            //HCNetSDK.CopyMemory(DecContain, pBuffer, dwBufSize);

            //if (dwDataType == HCNetSDK.NET_DVR_SYSHEAD)
            //{
            //    //#define NET_DVR_SYSHEAD     1       系统头数据
            //    InitDecoderHandle = new InitDecoderCallback(InitDecoder);
            //    this.BeginInvoke(InitDecoderHandle, new object[] { DecContain, dwBufSize });
            //}
            //else if (dwDataType == HCNetSDK.NET_DVR_STREAMDATA)
            //{
            //    //#define NET_DVR_STREAMDATA  2       流数据/视频数据
            //    if (InputDecoderHandle == null)
            //        InputDecoderHandle = new InputDecoderCallback(InputDecoder);
            //    this.BeginInvoke(InputDecoderHandle, new object[] { DecContain, dwBufSize });
            //}
        }

        int pWidth, pHeight;
        private delegate void InitDecoderCallback(IntPtr pBuffer, uint dwBufSize);
        private void InitDecoder(IntPtr pBuffer, uint dwBufSize)
        {
            do
            {
                if (!HCNetSDK.PlayM4_GetPort(ref m_iPort)) break;

                if (!HCNetSDK.PlayM4_SetStreamOpenMode(m_iPort, HCNetSDK.STREAME_REALTIME)) break;

                if (!HCNetSDK.PlayM4_OpenStream(m_iPort, pBuffer, dwBufSize, 1024 * 1024)) break;

                if (!HCNetSDK.PlayM4_GetPictureSize(m_iPort, out pWidth, out pHeight)) break;

                if (!HCNetSDK.PlayM4_SetDecCBStream(m_iPort, 1)) break;

                DecCBCallbackHandle = new HCNetSDK.DecCBFun(DecCallBack);
                if (!HCNetSDK.PlayM4_SetDecCallBack(m_iPort, DecCBCallbackHandle)) break;

                if (!HCNetSDK.PlayM4_Play(m_iPort, IntPtr.Zero)) break;

            } while (false);

            Marshal.FreeHGlobal(pBuffer);
        }

        private delegate void InputDecoderCallback(IntPtr pBuffer, uint dwBufSize);
        void InputDecoder(IntPtr pBuffer, uint dwBufSize)
        {
            HCNetSDK.PlayM4_InputData(m_iPort, pBuffer, dwBufSize);

            Marshal.FreeHGlobal(pBuffer);
        }

        int ticks = 0;
        private void DecCallBack(int nPort, IntPtr pBuf, int nSize, ref FRAME_INFO pFrameInfo, int nReserved1, int nReserved2)
        {
            //return;
            if (++ticks % 5 != 0) return;
            else ticks = 0;

            long span = DateTime.Now.Ticks;

#if DECODE_RGB
                //RGB流
                ImageProcessing.DecodeRGB(pBuf, bmpDecode);
#else
            //灰度流
            ImageProcessing.DecodeGrey(pBuf, bmpDecode);
#endif

#if ANALYZE

            //边缘模糊化
            ImageProcessing.Fuzzy(bmpDecode, bmpVision, pCenter);

            //边界提取
            ImageProcessing.Boundary(bmpVision, bmpBoundary);

            //兴趣灰度增强
            ImageProcessing.GreyEnhance(bmpVision, bmpGreyEnhance);

            //抽象图
            ImageProcessing.Abstract(bmpVision, bmpAbstract, sizeBlock, sizeMove);

            //稳定流
            ImageProcessing.StableStream(bmpVision, bmpStable);

            //动态流
            ImageProcessing.Subtract(bmpVision, bmpSubtract);

            //消抖流
            ImageProcessing.EliminateShake(bmpVision, bmpShake);

#endif

            span = (DateTime.Now.Ticks - span) / 10000;

            this.Invoke(new SetWindowTextCallback(SetWindowText), new object[] { span.ToString() + "ms" });

            PanelInvalidate();
        }

        delegate void PanelInvalidateCallback();
        void PanelInvalidate()
        {
            if (this.IsDisposed) return;

            if (this.InvokeRequired)
            {
                this.Invoke(new PanelInvalidateCallback(PanelInvalidate));
            }
            else
            {
                this.Invalidate();
            }
        }

        delegate void SetWindowTextCallback(string text);
        void SetWindowText(string text)
        {
            if (this.IsDisposed) return;

            if (this.InvokeRequired)
            {
                this.Invoke(new SetWindowTextCallback(SetWindowText), new object[] { text });
            }
            else
            {
                this.Text = text;
            }
        }

        bool isPaint = false;
        protected override void OnPaint(PaintEventArgs e)
        {
            try
            {
                base.OnPaint(e);

                if (isPaint) return;

                isPaint = true;



                lock (bmpDecode)
                {
                    if (bmpDecode != null) e.Graphics.DrawImage(bmpDecode, pDecode.Bounds);
                }

                lock (bmpStable)
                {
                    if (bmpStable != null) e.Graphics.DrawImage(bmpStable, pStable.Bounds);
                }

                lock (bmpSubtract)
                {
                    if (bmpSubtract != null) e.Graphics.DrawImage(bmpSubtract, pSubtract.Bounds);
                }

                lock (bmpShake)
                {
                    if (bmpShake != null) e.Graphics.DrawImage(bmpShake, pShake.Bounds);
                }
#if ANALYZE
                lock (bmpVision)
                {
                    e.Graphics.DrawImage(bmpVision,
                        pFuzzy.Bounds,
                        new Rectangle(0, 0, bmpVision.Width, bmpVision.Height),
                        GraphicsUnit.Pixel);

                    e.Graphics.DrawRectangle(Pens.Red, rectCenter);
                }

                lock (bmpBoundary)
                {
                    e.Graphics.DrawImage(bmpBoundary,
                        pBoundary.Bounds,
                        new Rectangle(0, 0, bmpBoundary.Width, bmpBoundary.Height),
                        GraphicsUnit.Pixel);
                }

                lock (bmpGreyEnhance)
                {
                    e.Graphics.DrawImage(bmpGreyEnhance,
                        pEnhance.Bounds,
                        new Rectangle(0, 0, bmpGreyEnhance.Width, bmpGreyEnhance.Height),
                        GraphicsUnit.Pixel);
                }

                lock (bmpAbstract)
                {
                    e.Graphics.DrawImage(bmpAbstract,
                        pAbstract.Bounds,
                        new Rectangle(0, 0, bmpAbstract.Width, bmpAbstract.Height),
                        GraphicsUnit.Pixel);
                }
#endif

            }
            catch (Exception Ex)
            {

                throw Ex;
            }


            isPaint = false;
        }

        private void rBCIF_CheckedChanged(object sender, EventArgs e)
        {
            if (rBCIF.Checked)
            {
                this.pStream.Size = new Size(352, 288);
                this.lDecode.Left -= 352;
                this.btnData.Left -= 352;
                this.pDecode.Left -= 352;
                this.pDecode.Size = new Size(352, 288);
                this.Width -= 704;
                this.Height -= 288;
            }
            else
            {
                this.pStream.Size = new Size(704, 576);
                this.lDecode.Left += 352;
                this.btnData.Left += 352;
                this.pDecode.Left += 352;
                this.pDecode.Size = new Size(704, 576);
                this.Width += 704;
                this.Height += 288;
            }
        }

        private void pStream_MouseDown(object sender, MouseEventArgs e)
        {
            pCenter = new Point(e.X * 2, e.Y * 2);
            rectCenter = new Rectangle(
                    (pDecode.Bounds.X + pCenter.X / 2 - sizeVision.Width / 4),
                    (pDecode.Bounds.Y + pCenter.Y / 2 - sizeVision.Height / 4),
                    sizeVision.Width / 2,
                    sizeVision.Height / 2);
        }

        #region 云镜控制
        uint command = 0;
        private void bUp_MouseDown(object sender, MouseEventArgs e)
        {
            command = (uint)HCNetSDK.PTZCommandEnum.TILT_UP;
            HCNetSDK.NET_DVR_PTZControlWithSpeed(lRealHandle, command, 0, (uint)hSBSpeed.Value);
        }

        private void bDown_MouseDown(object sender, MouseEventArgs e)
        {
            command = (uint)HCNetSDK.PTZCommandEnum.TILT_DOWN;
            HCNetSDK.NET_DVR_PTZControlWithSpeed(lRealHandle, command, 0, (uint)hSBSpeed.Value);
        }

        private void bLeft_MouseDown(object sender, MouseEventArgs e)
        {
            command = (uint)HCNetSDK.PTZCommandEnum.PAN_LEFT;
            HCNetSDK.NET_DVR_PTZControlWithSpeed(lRealHandle, command, 0, (uint)hSBSpeed.Value);
        }

        private void bRight_MouseDown(object sender, MouseEventArgs e)
        {
            command = (uint)HCNetSDK.PTZCommandEnum.PAN_RIGHT;
            HCNetSDK.NET_DVR_PTZControlWithSpeed(lRealHandle, command, 0, (uint)hSBSpeed.Value);
        }

        private void bWide_MouseDown(object sender, MouseEventArgs e)
        {
            command = (uint)HCNetSDK.PTZCommandEnum.ZOOM_OUT;
            HCNetSDK.NET_DVR_PTZControl_EX(lRealHandle, command, 0);
        }

        private void bTele_MouseDown(object sender, MouseEventArgs e)
        {
            command = (uint)HCNetSDK.PTZCommandEnum.ZOOM_IN;
            HCNetSDK.NET_DVR_PTZControl_EX(lRealHandle, command, 0);
        }

        private void bNear_MouseDown(object sender, MouseEventArgs e)
        {
            command = (uint)HCNetSDK.PTZCommandEnum.FOCUS_NEAR;
            HCNetSDK.NET_DVR_PTZControl_EX(lRealHandle, command, 0);
        }

        private void bFar_MouseDown(object sender, MouseEventArgs e)
        {
            command = (uint)HCNetSDK.PTZCommandEnum.FOCUS_FAR;
            HCNetSDK.NET_DVR_PTZControl_EX(lRealHandle, command, 0);
        }

        private void bPTZ_MouseUp(object sender, MouseEventArgs e)
        {
            HCNetSDK.NET_DVR_PTZControl_EX(lRealHandle, command, 1);
        }
        #endregion
        
    }
}
